/*
 * PacketEditor.hpp
 *
 *  Created on: 21.04.2011
 *      Author: mifodix
 */

#ifndef PACKETEDITOR_HPP_
#define PACKETEDITOR_HPP_

#ifndef __cplusplus
#error Need C++-compile to process this file
#endif

#include <stdint.h>
#include <string.h>
#include <list>
#include "Option.hpp"
#include "NetUtils.hpp"

#define MAIN_SIZE 236
#define MAX_PACKET_SIZE 576
#define MAGIC_COOKIE_SIZE 4
#define MAGIC_COOKIE_1 99
#define MAGIC_COOKIE_2 130
#define MAGIC_COOKIE_3 83
#define MAGIC_COOKIE_4 99
#define END_OPTION 255
/*
 *
 */
class PacketEditor
{
private:
	//содержимое пакета
	unsigned char op;//Тип сообщения. Может принимать два значения: BOOTREQUEST (1, запрос от клиента к серверу) и BOOTREPLY (2, ответ от сервера к клиенту).
	unsigned char htype;//Тип аппаратного адреса. Допустимые значения этого поля определены в RFC «Assigned Numbers». Например, для MAC-адреса Ethernet 10 Мбит/с это поле принимает значение 1.
	unsigned char hlen;//Длина аппаратного адреса в байтах. Для MAC-адреса Ethernet — 6.
	unsigned char hops;//Количество промежуточных маршрутизаторов (так называемых агентов ретрансляции DHCP), через которые прошло сообщение. Клиент устанавливает это поле в 0.
	uint32_t xid;//	Уникальный идентификатор транзакции, генерируемый клиентом в начале процесса получения адреса.
	uint16_t secs;//Время в секундах с момента начала процесса получения адреса. Может не использоваться (в этом случае оно устанавливается в 0).
	uint16_t flags;//Поле для флагов — специальных параметров протокола DHCP.
	uint32_t ciaddr;//	IP-адрес клиента. Заполняется только в том случае, если клиент уже имеет собственный IP-адрес и способен отвечать на запросы ARP (это возможно, если клиент выполняет процедуру обновления адреса по истечении срока аренды).
	uint32_t yiaddr;//Новый IP-адрес клиента, предложенный сервером.
	uint32_t siaddr;//IP-адрес сервера. Возвращается в предложении DHCP (см. ниже).
	uint32_t giaddr;//IP-адрес агента ретрансляции, если таковой участвовал в процессе доставки сообщения DHCP до сервера.
	char chaddr[16];//Аппаратный адрес (обычно MAC-адрес) клиента.
	char sname[64];//Необязательное имя сервера в виде нуль-терминированной строки.
	char file[128];//Необязательное имя файла на сервере, используемое бездисковыми рабочими станциями при удалённой загрузке. Как и sname, представлено в виде нуль-терминированной строки.
	std::list <Option> options;//Поле опций DHCP. Здесь указываются различные дополнительные параметры конфигурации. В начале этого поля указываются четыре особых байта со значениями 99, 130, 83, 99 («волшебные числа»), позволяющие серверу определить наличие этого поля. Поле имеет переменную длину, однако DHCP-клиент должен быть готов принять DHCP-сообщение длиной в 576 байт (в этом сообщении поле options имеет длину 312 байт).
public:
	PacketEditor();
	PacketEditor(const char *packet, size_t size);
	PacketEditor(const PacketEditor &copy);
	PacketEditor& operator=(const PacketEditor &ob);
	virtual ~PacketEditor();
	Option* FindOption(unsigned char code);
    char *GetChaddr() const;
    uint32_t GetCiaddr() const;
    char *GetFile() const;
    uint16_t GetFlags() const;
    uint32_t GetGiaddr() const;
    unsigned char GetHlen() const;
    unsigned char GetHops() const;
    unsigned char GetHtype() const;
    unsigned char GetOp() const;
    std::list<Option> GetOptions() const;
    size_t GetPacket(char *&packet);
    uint16_t GetSecs() const;
    uint32_t GetSiaddr() const;
    char *GetSname() const;
    uint32_t GetXid() const;
    uint32_t GetYiaddr() const;
    void SetChaddr(const char *chaddr);
    void SetCiaddr(uint32_t ciaddr);
    void SetFile(const char *file);
    void SetFlags(uint16_t flags);
    void SetGiaddr(uint32_t giaddr);
    void SetHlen(unsigned char hlen);
    void SetHops(unsigned char hops);
    void SetHtype(unsigned char htype);
    void SetOp(unsigned char op);
    void SetOptions(std::list <Option> options);
    void SetPacket(const char *packet, size_t size);
    void SetSecs(uint16_t secs);
    void SetSiaddr(uint32_t siaddr);
    void SetSname(const char *sname);
    void SetXid(uint32_t xid);
    void SetYiaddr(uint32_t yiaddr);
    bool AddOption(unsigned char code, unsigned char len, const char *data);
    bool RemoveOption(unsigned char code);
    void ClearOptions();
};

#endif /* PACKETEDITOR_HPP_ */
